﻿using System;
using System.ComponentModel;
using System.Drawing;
using System.Web.Caching;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using CKS.Sandbox.DailyDilbert.Proxy;
using Microsoft.SharePoint.Utilities;

namespace CKS.Sandbox.DailyDilbert.WebParts
{
    /// <summary>
    /// Daily Dilbert Strip Web Part class
    /// </summary>
    [ToolboxItemAttribute(false)]
    public class DailyDilbertStripWebPart : WebPart
    {
        [Personalizable(PersonalizationScope.Shared),
        WebBrowsable(true),
        WebDescription("The Url of the feed for the Daily Dilbert Strip. This is read-only as the implementation is specific to the feed."),
        WebDisplayName("Daily Dilbert Feed Url."),
        Category("CKS WebPart Property")]
        public string FeedUrl
        {
            get
            {
                return "http://feeds.dilbert.com/DilbertDailyStrip";
            }
            set
            {
                // Dummy Setter
                // Apparently toolpart can't display read-only properties
            }
        }

        /// <summary>
        /// Cache key to store the Dilbert strip image Url for the day
        /// </summary>
        private const string CacheKey = "DailyDilbertFeedCacheKey";

        /// <summary>
        /// Default constructor
        /// </summary>
        public DailyDilbertStripWebPart()
        {
        }

        /// <summary>
        /// On Load
        /// </summary>
        /// <param name="e"></param>
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
        }

        /// <summary>
        /// Create Child Controls
        /// </summary>
        protected override void CreateChildControls()
        {
            // Create a table cell to contain the Dilbert strip image
            Table tbl = new Table();
            this.Controls.Add(tbl);
            TableRow row = new TableRow();
            tbl.Controls.Add(row);
            TableCell cell = new TableCell();
            cell.VerticalAlign = VerticalAlign.Middle;
            cell.HorizontalAlign = System.Web.UI.WebControls.HorizontalAlign.Center;
            row.Controls.Add(cell);
            DailyDilbertFeedData msg = null;
            Label error = null;
            bool foundInCache = false;
            Cache cacheObj = null;

            try
            {
                cacheObj = this.Page.Cache;

                // If in cache, pick the feed data from cache
                if (cacheObj[CacheKey] != null)
                {
                    foundInCache = true;
                    msg = cacheObj[CacheKey] as DailyDilbertFeedData;
                }
                else
                {
                    // Execute proxy operation
                    msg = SPUtility.ExecuteRegisteredProxyOperation(
                        "CKS.Sandbox.DailyDilbert.Proxy, Version=1.0.0.0, Culture=neutral, PublicKeyToken=7236f2dfb8dd25cd",
                        "CKS.Sandbox.DailyDilbert.Proxy.DailyDilbertProxyOperation",
                        new DailyDilbertProxyOperationArgs(this.FeedUrl)) as DailyDilbertFeedData;
                }
            }
            catch (Exception ex)
            {
                msg = null;
                error = GetErrorLabel("Exception occured. Failed to retrieve items from feed.", ex);
                cell.Controls.Add(error);
            }

            if (msg != null)
            {
                if (msg.IsError == false)
                {
                    if (msg.Items.Count > 0)
                    {
                        // Retrieve the image Url and set to an image element
                        System.Web.UI.WebControls.Image img = new System.Web.UI.WebControls.Image();
                        DailyDilbertFeedItemData item = msg.Items[0];
                        img.AlternateText = item.Title;
                        img.ImageUrl = item.ImageSource;
                        cell.Controls.Add(img);

                        if (!foundInCache)
                        {
                            // If feed data is retrieved through a proxy operation, Cache it.
                            // Cache is absolute expiration.
                            // Expiration time is  (LastUpdatedDate + 1 day)  in local server time.
                            DateTime expirationTime = msg.LastUpdatedDate.AddDays(1).ToLocalTime().DateTime;
                            cacheObj.Insert(CacheKey, msg, null, expirationTime, System.Web.Caching.Cache.NoSlidingExpiration, CacheItemPriority.Normal, null);
                        }
                    }
                    else
                    {
                        error = GetErrorLabel("Feed doesn't contain any items.");
                        cell.Controls.Add(error);
                    }
                }
                else
                {
                    error = GetErrorLabel(msg.ErrorMessage);
                    cell.Controls.Add(error);
                }
            }
            else
            {
                error = GetErrorLabel("Failed to retrieve items from feed.");
                cell.Controls.Add(error);
            }
        }

        /// <summary>
        /// Returns a Label with error message from an exception.
        /// </summary>
        /// <param name="message">The contextual error message</param>
        /// <param name="ex">The exception</param>
        /// <returns>Label control with message set</returns>
        private static Label GetErrorLabel(string message, Exception ex)
        {
            return GetErrorLabel(string.Concat(message, " ", ex.Message));
        }

        /// <summary>
        /// Returns a label with error message.
        /// </summary>
        /// <param name="message">The contextual error message</param>
        /// <returns>Label control with message set</returns>
        private static Label GetErrorLabel(string message)
        {
            Label lbl = new Label();
            lbl.ID = "lable1";
            lbl.Text = System.Web.HttpUtility.HtmlEncode(message);
            lbl.ForeColor = Color.DarkRed;

            return lbl;
        }
    }
}
